/**
* \file affichageSDL.c
* \brief Comprend les fonctions et les procédures qui permettent d'afficher le jeu en SDL
*/

#include <stdio.h>
#include <stdlib.h>

#include "Parametres.h"
#include "Combinaison.h"
#include "affichageSDL.h"
#include "Jeu.h"
#include "math.h"

#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>


/**
* \fn SDL_Surface *chargerImage(const char* filename)
* \brief La procédure chargerImage permet de charger une image
*/

SDL_Surface *chargerImage(const char* filename)
{
	//Surface tampon qui nous servira pour charger l'image
	SDL_Surface* imageChargee = NULL;

	//L'image optimisée qu'on va utiliser
	SDL_Surface* imageOptimisee = NULL;

	//Chargement de l'image
	imageChargee = SDL_LoadBMP( filename );

	//Si le chargement se passe bien
	if( imageChargee != NULL ) {
		//Création de l'image optimisée
		imageOptimisee = SDL_DisplayFormat( imageChargee );

		//Libération de l'ancienne imagevalgrind --tool=memcheck --leak-check=full ./prog
		SDL_FreeSurface( imageChargee );
	}

    else
    {
        printf("Erreur dans le chargement de l'image");
    }

	//On retourne l'image optimisée
	return imageOptimisee;
}



/**
* \fn void appliquerSurface(SDL_Surface* source, SDL_Surface* destination, int x, int y)
* \brief La procédure appliquerSurface permet d'appliquer une image sur une surface SDL
*/

void appliquerSurface(SDL_Surface* source, SDL_Surface* destination, int x, int y)
{
	// Rectangle temporaire
	SDL_Rect offset;

	offset.x = x;
	offset.y = y;

	// Blit de la surface
	SDL_BlitSurface(source, NULL, destination, &offset);
}



/**
* \fn void afficheSDL (Jeu jeu, Parametres param, SDL_Surface *screen)
* \brief La procédure afficheSDL permet d'afficher les différentes surfaces SDL d'une partie
*/

void afficheSDL (Jeu jeu, Parametres param, SDL_Surface *screen)
{
    int i, j;
    i=0;
    j=0;

    int hauteurCase;
    hauteurCase = 60;

    Combinaison comb;
    initCombinaison (&comb,param);

    SDL_Surface *plateauDeJeu = NULL;
    SDL_Surface *infosPartie = NULL;
    SDL_Surface *affichageIndicationsPartie = NULL;


	//Chargement des images selon le niveau choisi
	if (param.taille == 3)
    {
        plateauDeJeu = chargerImage ("data/PlateauNiv3.bmp");
    }

    else if (param.taille == 4)
    {
        plateauDeJeu = chargerImage ("data/PlateauNiv4.bmp");
    }

    else
    {
        plateauDeJeu = chargerImage ("data/PlateauNiv5.bmp");
    }

    affichageIndicationsPartie = chargerImage("data/Indications.bmp");
    infosPartie = chargerImage("data/InfosPartie.bmp");

    //On applique le fond sur l'écran
    appliquerSurface(plateauDeJeu, screen, 0, 0);
    appliquerSurface(affichageIndicationsPartie, screen, 660, 0);
    appliquerSurface(infosPartie, screen, 780, 0);

    //Pour afficher les combinaisons testées
    for (i=0; i<(10 - jeu.nbEssais); i++)
    {
        for (j=0; j<param.taille; j++)
        {
            afficheCombinaison(param, screen, jeu.tabCombinaisonsTestees[i].tab, 60, (540-i*hauteurCase));
        }
    }

    SDL_FreeSurface(plateauDeJeu);
    SDL_FreeSurface(affichageIndicationsPartie);
    SDL_FreeSurface(infosPartie);
}



// Fonctions pour afficher les indications de jeu

/**
* \fn void afficheIndicationPionsBienPlaces(Jeu jeu, SDL_Surface *screen)
* \brief La procédure afficheIndicationPionsBienPlaces permet d'indiquer
*        le nombre de pions bien placés de la combinaison testée par rapport à la combinaison secrète.
*/

void afficheIndicationPionsBienPlaces(Jeu jeu, SDL_Surface *screen)
{
    int i;
    i=0;
    int hauteurCase, debutZoneIndications;
    hauteurCase=60;
    debutZoneIndications=660;

    SDL_Surface *indicationPionsBienPlaces = NULL;


    for (i=0; i<(10 - jeu.nbEssais); i++)
    {
        if (jeu.tabNbPionsBienPlaces[i] == 0)
        {
            indicationPionsBienPlaces = chargerImage("data/num0.bmp");
        }

        else if (jeu.tabNbPionsBienPlaces[i] == 1)
        {
            indicationPionsBienPlaces = chargerImage("data/num1.bmp");
        }

        else if (jeu.tabNbPionsBienPlaces[i] == 2)
        {
            indicationPionsBienPlaces = chargerImage("data/num2.bmp");
        }

        else if (jeu.tabNbPionsBienPlaces[i] == 3)
        {
            indicationPionsBienPlaces = chargerImage("data/num3.bmp");
        }

        else if (jeu.tabNbPionsBienPlaces[i] == 4)
        {
            indicationPionsBienPlaces = chargerImage("data/num4.bmp");
        }

        else if (jeu.tabNbPionsBienPlaces[i] == 5)
        {
            indicationPionsBienPlaces = chargerImage("data/num5.bmp");
        }

        appliquerSurface(indicationPionsBienPlaces, screen, debutZoneIndications, (540-i*hauteurCase));

    }
    SDL_FreeSurface(indicationPionsBienPlaces);
}



/**
* \fn void afficheIndicationPionsBonneCouleur(Jeu jeu, SDL_Surface *screen)
* \brief La procédure afficheIndicationPionsBonneCouleur permet d'indiquer le nombre
*        de pions mal placés mais dont la couleur fait partie de la combinaison secrète.
*/

void afficheIndicationPionsBonneCouleur(Jeu jeu, SDL_Surface *screen)
{
    int i;
    i=0;
    int largeurCase, hauteurCase, debutZoneIndications;
    debutZoneIndications=660;
    largeurCase=60;
    hauteurCase=60;

    SDL_Surface *indicationPionsBonneCouleur = NULL;

    for (i=0; i<(10 - jeu.nbEssais); i++)
    {
        SDL_Flip(screen);

        if (jeu.tabNbPionsBonneCouleur[i] == 0)
        {
            indicationPionsBonneCouleur = chargerImage("data/num0.bmp");
        }

        else if (jeu.tabNbPionsBonneCouleur[i] == 1)
        {
            indicationPionsBonneCouleur = chargerImage("data/num1.bmp");
        }

        else if (jeu.tabNbPionsBonneCouleur[i] == 2)
        {
            indicationPionsBonneCouleur = chargerImage("data/num2.bmp");
        }

        else if (jeu.tabNbPionsBonneCouleur[i] == 3)
        {
            indicationPionsBonneCouleur = chargerImage("data/num3.bmp");
        }

        else if (jeu.tabNbPionsBonneCouleur[i] == 4)
        {
            indicationPionsBonneCouleur = chargerImage("data/num4.bmp");
        }

        else if (jeu.tabNbPionsBonneCouleur[i] == 5)
        {
            indicationPionsBonneCouleur = chargerImage("data/num5.bmp");
        }

        appliquerSurface(indicationPionsBonneCouleur, screen, (debutZoneIndications+largeurCase), (540-i*hauteurCase));

    }
    SDL_FreeSurface(indicationPionsBonneCouleur);
}



/**
* \fn int deroulementJeuSDL(SDL_Surface* screen, Jeu* jeu, Parametres param)
* \brief La procédure deroulementJeuSDL comprend les principales actions
*        nécessaires au déroulement d'une partie en SDL
*/

int deroulementJeuSDL(SDL_Surface* screen, Jeu* jeu, Parametres param)
{

// Pour afficher du texte sur une surface SDL
    //Initialisation de SDL_TTF
    if (TTF_Init() == -1)
    {
        printf("Problème TTF_Init \n");
    }

    TTF_Font *police = NULL;

    //La couleur de la police
    SDL_Color textColor = {0, 0, 153};

    //Ouverture de la police
    police = TTF_OpenFont("data/comic.ttf", 32);

    if(police == NULL)
    {
        printf("Problème chargement police \n");
    }


    SDL_Surface *partieGagnee = NULL;
    SDL_Surface *partiePerdue = NULL;
    SDL_Surface *score = NULL;
    SDL_Surface *temps = NULL;

    SDL_Event event;

    // Déclarations et initialisations des variables utilisées
    int notechap=1;
    int continuer=1;
    int heureDebut=0;
    int heureFin=0;
    int dureePartie=0;
    int minute=0;
    int seconde=0;
    char txtScore[100];
    char txtTemps[100];
    int i=0;
    int k=0;
    int x=0;
    int y=0;

    // Pour récupérer l'heure au début de la partie
    heureDebut = SDL_GetTicks();

    do
    {
        Combinaison CombTest;
        initCombinaison(&CombTest, param);

        afficheSDL(*jeu, param, screen);

        afficheIndicationPionsBienPlaces(*jeu, screen);
        afficheIndicationPionsBonneCouleur(*jeu, screen);

        // Pour afficher le score
        sprintf(txtScore,"%d", jeu->score);
        score = TTF_RenderText_Blended(police, txtScore, textColor);
        appliquerSurface(score, screen, 850, 120);

        CombTest = saisieCombinaisonSDL(param, screen, &notechap, 60, 600);
        remplirTableaux (jeu, param, &CombTest, k);
        calculScore(jeu, param, i);
        jeu->nbEssais--;
        k++;
        libereCombinaison(&CombTest);
        i++;
    }
    while((k <10) && (jeu->nbEssais > 0)  && (pionsBienPlaces(&jeu->tabCombinaisonsTestees[i-1], &jeu->combinaisonSecrete) != param.taille)&& notechap);

    // Pour récupérer l'heure à la fin de la partie
    heureFin = SDL_GetTicks();

    // Calcul de la durée de la partie
    dureePartie = heureFin - heureDebut;

    // Calcul pour mettre les millisecondes en minute et seconde
    minute = (dureePartie / 60000);
    seconde = ((dureePartie - minute*60000) / 1000);

    // Pour afficher la durée de la partie
    if (seconde <= 9)
    {
        sprintf(txtTemps, "%d : 0%d", minute, seconde);
    }
    else
    {
         sprintf(txtTemps, "%d : %d", minute, seconde);
    }
    temps = TTF_RenderText_Blended(police, txtTemps, textColor);


/* Si la partie est gagnée */
    if (pionsBienPlaces(&jeu->tabCombinaisonsTestees[i-1], &jeu->combinaisonSecrete) == param.taille&&notechap)
    {
        afficheSDL(*jeu, param, screen);
        afficheIndicationPionsBienPlaces(*jeu, screen);
        afficheIndicationPionsBonneCouleur(*jeu, screen);

        jeu->score = jeu->score + 20*jeu->nbEssais; /* Partie gagnée */

        while (continuer)
        {
            SDL_Flip(screen);
            partieGagnee = chargerImage ("data/InfosPartieGagnee.bmp");
            appliquerSurface(partieGagnee, screen, 780, 0);

            /* Pour afficher le score en fin de partie */
            sprintf(txtScore,"%d", jeu->score);
            score = TTF_RenderText_Blended(police, txtScore, textColor);
            appliquerSurface(score, screen, 840, 80);

            appliquerSurface(temps, screen, 830, 220);

            afficheCombinaison(param, screen, jeu->combinaisonSecrete.tab, 60, 600);
            SDL_WaitEvent(&event);

            switch(event.type)
            {
                case SDL_QUIT: // si la fenêtre est fermée (appui sur la croix)
                    continuer = 0;
                    notechap=0;
                    break;

                case SDL_KEYDOWN: // si type = TOUCHE APPUYE
                    switch (event.key.keysym.sym)
                    {
                        case SDLK_ESCAPE: // si touche = ECHAP
                            continuer = 0;
                              notechap=0;
                            break;

                        default:
                            break;
                    }


                case SDL_MOUSEBUTTONUP:
                    //Si le bouton gauche de la souris est pressé
                    if(event.button.button == SDL_BUTTON_LEFT)
                    {
                            //Récupération des coordonnées de la souris
                            x = event.button.x;
                            y = event.button.y;


                            //En fonction de la position de la souris
                            if((x >= 780) && (x <= 925) && (y >= 525) && (y <= 550)) // Clic sur "Menu"
                            {
                                continuer= 0;

                            }

                            if((x >= 820) && (x <= 950) && (y >= 595) && (y <= 630)) // Clic sur "Quitter"
                            {
                                continuer = 0;
                                  notechap=0;
                            }
                    }
                        break;

                 default:
                    break;
            }
        }
    }


/* Si la partie est perdue */

    else if(jeu->nbEssais == 0 && notechap==1)
    {
        afficheSDL(*jeu, param, screen);
        afficheIndicationPionsBienPlaces(*jeu, screen);
        afficheIndicationPionsBonneCouleur(*jeu, screen);

        jeu->score = jeu->score - 30; /* Partie perdue */

        while (continuer)
        {
            SDL_Flip(screen);
            partiePerdue = chargerImage ("data/InfosPartiePerdue.bmp");
            appliquerSurface(partiePerdue, screen, 780, 0);

            /* Pour afficher le score en fin de partie */
            sprintf(txtScore,"%d", jeu->score);
            score = TTF_RenderText_Blended(police, txtScore, textColor);
            appliquerSurface(score, screen, 840, 80);

            appliquerSurface(temps, screen, 830, 220);
            afficheCombinaison(param, screen, jeu->combinaisonSecrete.tab, 60, 600);
            SDL_WaitEvent(&event);

            switch(event.type)
            {
                case SDL_QUIT: // si la fenêtre est fermée (appui sur la croix)
                    continuer = 0;
                    notechap=0;
                    break;


                case SDL_KEYDOWN: // si type = TOUCHE APPUYE
                    switch (event.key.keysym.sym)
                    {
                        case SDLK_ESCAPE: /*si touche = ECHAP*/
                            continuer = 0;
                            notechap=0;
                            break;

                        default:
                            break;
                    }


                case SDL_MOUSEBUTTONUP:
                    /*Si le bouton gauche de la souris est pressé*/
                    if(event.button.button == SDL_BUTTON_LEFT)
                    {
                            /*Récupération des coordonnées de la souris*/
                            x = event.button.x;
                            y = event.button.y;


                            //En fonction de la position de la souris
                            if((x >= 780) && (x <= 925) && (y >= 525) && (y <= 550)) // Clic sur "Menu"
                            {
                                continuer= 0;

                            }

                            if((x >= 820) && (x <= 950) && (y >= 595) && (y <= 630)) // Clic sur "Quitter"
                            {
                                continuer = 0;
                                  notechap=0;

                            }
                        }
                        break;

                 default:
                    break;

            }
        }
    }

    SDL_FreeSurface(partieGagnee);
    SDL_FreeSurface(partiePerdue);
    SDL_FreeSurface(score);
    SDL_FreeSurface(temps);

    TTF_CloseFont(police);
    TTF_Quit();
    return notechap;

}
